﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Xml.Linq;
using AutoLoL.Dialogs;
using AutoLoL.Entities;
using AutoLoL.Logic;
using AutoLoL.Logic.Automation;
using AutoLoL.Logic.Factories;
using AutoLoL.Logic.Game;
using AutoLoL.Logic.Repositories;
using AutoLoL.Logic.Windows;
using AutoLoL.Shared;
using AutoLoL.Tabs;
using SHDocVw;

namespace AutoLoL
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private const int BUILDS_TAB_INDEX = 2;

        private SettingsTab _settingsTab;
        private BuildsTab _buildsTab;

        //private MinimizeToTray _minimizeToTray;
        private BackgroundWorker _updateBackgroundWorker;
        private BackgroundWorker _dataBackgroundWorker;

        private System.Windows.Forms.Timer _autoTimer = new System.Windows.Forms.Timer();
        private DateTime _checkAutoLoginAfter = DateTime.Now;
        private DateTime _checkLauncherAfter = DateTime.Now;

        public MainWindow()
        {
            InitializeComponent();

            // Create controls
            _settingsTab = new SettingsTab();
            _settingsTab.OnSettingsSaved += new SettingsSavedHandler(SettingsTab_OnSettingsSaved);
            _settingsTab.OnBuildsImported += new BuildsImportedHandler(SettingsTab_OnBuildsImported);
            SettingsTabItem.Content = _settingsTab;

            SetDataTabsEnabled(false);

            AutoChatTabItem.Content = new AutoChatTab();

            // Initialize the factories
            ItemFactory.Instance.SetRepository(new RafItemRepository());
            ChampionFactory.Instance.SetRepository(new RafChampionRepository());
            MasteryFactory.Instance.SetRepository(new LocalMasteryRepository());
            SummonerSpellFactory.Instance.SetRepository(new LocalSummonerSpellRepository());

            // Preload local data (fast)
            MasteryFactory.Instance.GetMasteryBuild();
            SummonerSpellFactory.Instance.GetAll(MasteryFactory.Instance);

            // Start timer for automated actions
            _autoTimer.Interval = 500;
            _autoTimer.Tick += new EventHandler(AutoTimer_Tick);
            _autoTimer.Start();

            // Check for updates
            _updateBackgroundWorker = new BackgroundWorker();
            _updateBackgroundWorker.DoWork += new DoWorkEventHandler(UpdateBackgroundWorker_DoWork);
            _updateBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(UpdateBackgroundWorker_RunWorkerCompleted);
            _updateBackgroundWorker.RunWorkerAsync();

            // Preload background worker
            _dataBackgroundWorker = new BackgroundWorker();
            _dataBackgroundWorker.DoWork += new DoWorkEventHandler(DataBackgroundWorker_DoWork);
            _dataBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(DataBackgroundWorker_RunWorkerCompleted);

            // News
#if !DEBUG
            WebBrowser.Navigate(Constants.NEWS_PAGE_URL + "?version=" + Constants.APPLICATION_VERSION.Major + "." + Constants.APPLICATION_VERSION.Minor + "." + Constants.APPLICATION_VERSION.Build);
            ((DWebBrowserEvents2_Event)WebBrowser.ActiveXInstance).NewWindow3 += WebBrowser_NewWindow3;
#endif

            // Title
            Title = "AutoLoL v" + Constants.APPLICATION_VERSION.Major + "." + Constants.APPLICATION_VERSION.Minor + "." + Constants.APPLICATION_VERSION.Build;

            // TODO - Fix
            // Create minimize to tray instance
            //_minimizeToTray = new MinimizeToTray(this, UserSettings.Instance.IsMinimizeToTrayEnabled);

            // Update the updater
            UpdateUpdater();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Make sure the League of Legends directory is configured correctly
            while (!SettingsTab.IsValidLolDirectory(UserSettings.Instance.LolDirectory))
            {
                System.Windows.Forms.FolderBrowserDialog folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
                folderBrowserDialog.ShowNewFolderButton = false;
                folderBrowserDialog.Description = "Please select your League of Legends installation directory.";
                System.Windows.Forms.DialogResult result = folderBrowserDialog.ShowDialog();

                if (result == System.Windows.Forms.DialogResult.OK)
                {
                    string selectedPath = folderBrowserDialog.SelectedPath;
                    if (SettingsTab.IsValidLolDirectory(selectedPath))
                    {
                        UserSettings.Instance.LolDirectory = selectedPath;
                        UserSettings.Instance.Save();
                        break;
                    }
                }
                else
                {
                    Application.Current.Shutdown();
                    break;
                }
            }

            // Start League of Legends if AutoRun is enabled
            if (UserSettings.Instance.IsAutorunEnabled)
            {
                LaunchLeagueOfLegends();
            }

            // Set FirstRun to false
            if (UserSettings.Instance.FirstRun)
            {
                FirstRunContentControl.Visibility = Visibility.Visible;
                UserSettings.Instance.FirstRun = false;
                UserSettings.Instance.Save();
            }

            // Reload settings
            _settingsTab.UpdateFromUserSettings();
            SettingsTab_OnSettingsSaved();

            // Show the news page
            NewsWindowsFormsHost.Visibility = Visibility.Visible;

            // Load data
            _dataBackgroundWorker.RunWorkerAsync();
        }

        private void DataBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            ChampionFactory.Instance.GetAll();
            ItemFactory.Instance.GetAll();
        }

        private void DataBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            SetDataTabsEnabled(true);
        }

        private void SetDataTabsEnabled(bool isEnabled)
        {
            BuildsButton.IsEnabled = isEnabled;
            BuildsTabItem.IsEnabled = isEnabled;
            ModelTabItem.IsEnabled = isEnabled;

            Visibility visibility = (isEnabled ? Visibility.Collapsed : Visibility.Visible);
            LoadingContentControl.Visibility = visibility;
            BuildsTabLoadingControl.Visibility = visibility;
            ModelTabLoadingControl.Visibility = visibility;

            // Show / hide the lolm import button
            _settingsTab.ImportButtonEnabled = isEnabled;

            if (isEnabled)
            {
                _buildsTab = new BuildsTab();
                BuildsTabItem.Content = _buildsTab;

                ModelTabItem.Content = new ModelTab();
            }
            else if (!isEnabled)
            {
                BuildsTabItem.Content = null;
                ModelTabItem.Content = null;
            }
        }

        private void UpdateBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = false;

            try
            {
                XDocument updatesDoc = XDocument.Load(Constants.UPDATES_URL);
                List<Update> updates = updatesDoc.Root.Elements("update").Where(c =>
                    c.Attribute("version") != null
                    && c.Attribute("url") != null).Select(u => new Update()
                    {
                        Version = new Version(u.Attribute("version").Value),
                        Url = u.Attribute("url").Value
                    }).ToList();

                if (updates.Where(c => c.Version > Constants.APPLICATION_VERSION).Any())
                {
                    e.Result = true;
                }
            }
            catch { if (Debugger.IsAttached) throw; }
        }

        private void UpdateBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            bool result = (bool)e.Result;
            if (result)
            {
                UpdateContentControl.Visibility = Visibility.Visible;
            }
        }

        public void SettingsTab_OnSettingsSaved()
        {
            // TODO - Fix
            // Update MinimizeToTray settings
            //_minimizeToTray.IsEnabled = UserSettings.Instance.IsMinimizeToTrayEnabled;

            // Start AutoChat if enabled
            if (UserSettings.Instance.IsAutoChatEnabled)
            {
                AutoChat.StartListening();
            }
            else
            {
                AutoChat.StopListening();
            }

            // Enable Auto Login checkbox
            if (UserSettings.Instance.LolUsername.Length > 0
                && UserSettings.Instance.LolPasswordEncrypted.Length > 0)
            {
                if (!AutoLoginCheckBox.IsEnabled)
                {
                    AutoLoginCheckBox.IsEnabled = true;
                    AutoLoginCheckBox.IsChecked = (UserSettings.Instance.IsAutoLoginEnabled);
                }
            }
            else
            {
                AutoLoginCheckBox.IsEnabled = false;
                AutoLoginCheckBox.IsChecked = false;
            }
        }

        private void SettingsTab_OnBuildsImported()
        {
            if (_buildsTab != null)
            {
                _buildsTab.CreateBuildsControl();
            }
        }

        private void CloseHyperlink_Click(object sender, RoutedEventArgs e)
        {
            FirstRunContentControl.Visibility = Visibility.Collapsed;
        }

        /// <summary>
        /// Timer stuff
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AutoTimer_Tick(object sender, EventArgs e)
        {
            //// Auto Login
            try
            {
                if (UserSettings.Instance.LolUsername.Length > 0
                    && UserSettings.Instance.LolPasswordEncrypted.Length > 0
                    && AutoLoginCheckBox.IsChecked.Value)
                {
                    if (AutoLogin.Login())
                    {
                        AutoLoginCheckBox.IsChecked = false;
                    }
                }
            }
            catch
            {
                if (Debugger.IsAttached) throw;
            }
        }

        /// <summary>
        /// Opens the Builds tab
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BuildsButton_Click(object sender, RoutedEventArgs e)
        {
            RootTabControl.SelectedIndex = BUILDS_TAB_INDEX;
        }

        /// <summary>
        /// Tries to launch the updater and closes AutoLoL
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UpdaterButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                ConfirmDialog dialog = new ConfirmDialog(this, "Launching the updater will close AutoLoL, do you want to continue?");
                dialog.ShowDialog();

                if (dialog.DialogResult.HasValue && dialog.DialogResult.Value)
                {
                    UpdateUpdater();
                    Process.Start("AutoLoL.Updater.exe");
                    Close();
                }
            }
            catch
            {
                if (Debugger.IsAttached) throw;
            }
        }

        /// <summary>
        /// Tries to update the updater by replacing it with a new version
        /// </summary>
        public static void UpdateUpdater()
        {
            try
            {
                if (File.Exists("AutoLoL.Updater.new"))
                {
                    File.Delete("AutoLoL.Updater.exe");
                    File.Move("AutoLoL.Updater.new", "AutoLoL.Updater.exe");
                }
            }
            catch { if (Debugger.IsAttached) throw; }
        }

        /// <summary>
        /// Tries to launch Leage of Legends
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LaunchButton_Click(object sender, RoutedEventArgs e)
        {
            LaunchLeagueOfLegends();
        }

        /// <summary>
        /// Tries to launch League of Legends
        /// </summary>
        private void LaunchLeagueOfLegends()
        {
            bool isLaunced = false;

            if(UserSettings.Instance.IsAutoLoginEnabled)
            {
                AutoLoginCheckBox.IsChecked = true;
            }

            try
            {
                if (!string.IsNullOrEmpty(UserSettings.Instance.LolDirectory))
                {
                    string executable = System.IO.Path.Combine(UserSettings.Instance.LolDirectory, "lol.launcher.exe");

                    if (File.Exists(executable))
                    {
                        isLaunced = true;
                        Process.Start(executable);
                    }
                }
            }
            catch { if (Debugger.IsAttached) throw; }

            if (!isLaunced)
            {
                new ConfirmDialog(this, "Unable to launch League of Legends. Make sure your you have correctly configured your Game Directory in the settings tab.", "Error", false).ShowDialog();
            }
        }

        /// <summary>
        /// Delete crappy file created by League of Legends
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Closing(object sender, CancelEventArgs e)
        {
            try
            {
                if (File.Exists("maestro-server.log"))
                {
                    File.Delete("maestro-server.log");
                }
            }
            catch { if (Debugger.IsAttached) throw; }
        }

        /// <summary>
        /// Opens the League of Legends site
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LolImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Process.Start("http://www.leagueoflegends.com/");
        }

        /// <summary>
        /// Opens the AutoLoL codeplex page
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CodeplexImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Process.Start("http://autolol.codeplex.com/");
        }

        /// <summary>
        /// Opens a url
        /// </summary>
        private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
        {
            Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
            e.Handled = true;
        }

        /// <summary>
        /// Opens a url in the users default browser
        /// </summary>
        private void WebBrowser_NewWindow3(ref object ppDisp, ref bool Cancel, uint dwFlags, string bstrUrlContext, string bstrUrl)
        {
            Process.Start(bstrUrl);
            Cancel = true;
        }

        private void TimersButton_Click(object sender, RoutedEventArgs e)
        {
            Jungle_Timers.MainWindow w = new Jungle_Timers.MainWindow();
            w.Show();
        }
    }
}
